﻿@page "/ExInterDoc"
@using JavaDevToys.Rcl.Models
@using JavaDevToys.Rcl.Service
@using Microsoft.Extensions.DependencyInjection
@using Microsoft.JSInterop
@using System.Linq
@using System.Text
<h3>文档解析</h3>
<script>
    var require = { paths: { 'vs': 'https://cdn.masastack.com/npm/monaco-editor/0.34.1/min/vs' } };
</script>
<script src="https://cdn.masastack.com/npm/monaco-editor/0.34.1/min/vs/loader.js"></script>
<script src="https://cdn.masastack.com/npm/monaco-editor/0.34.1/min/vs/editor/editor.main.nls.js"></script>
<script src="https://cdn.masastack.com/npm/monaco-editor/0.34.1/min/vs/editor/editor.main.js"></script>
<MAlert Dismissible
Type="AlertType"
@bind-Value="_alert">
    @errMsg
</MAlert>
<div class="d-flex ml-5 mr-5">
    <MRadioGroup @bind-Value="projectType"
    Row>
        <MRadio Label="Java项目"
        Value="@("Java")">
        </MRadio>
        <MRadio Label="CSharp项目"
        Value="@("CSharp")">
        </MRadio>
    </MRadioGroup>
    <MButton Color="success" Class="mt-3 ml-5" OnClick="SaveSettings">
        保存设置
    </MButton>
</div>

<MCard>
    <MToolbar Color="blue">
        <MToolbarTitle>字段顺序</MToolbarTitle>
    </MToolbar>
    <MCardText>
        <MChipGroup @bind-Values="amenities"
        Column
        Multiple>
            @foreach (var item in TitleCols)
            {
                <MChip Filter
                Outlined>
                    @item
                </MChip>
            }
        </MChipGroup>

        @foreach (var item in docTitles)
        {
            <MChip Class="ma-2"
            Color="green"
            Outlined
            Close
            OnCloseClick="()=> DeleteDocTitle(item)">
                @item
            </MChip>
        }
    </MCardText>
</MCard>

<MCard Class="mt-2">
    <MToolbar Color="blue">
        <MToolbarTitle>类型映射</MToolbarTitle>
    </MToolbar>
    <MCardText>
        <div class="d-flex ml-5 mr-5">
            <MTextField @bind-Value="@docFile" FullWidth="false"
            Hint="文档字段"
            Label="输入文档字段">
            </MTextField>
            <MSelect Items="codeTypes"
            @bind-Value="@codeType"
            ItemText="u => u"
            ItemValue="u => u"
            Label="对应字段类型"
            Dense
            Outlined></MSelect>
            <MButton class="mx-2"
            Fab
            Small
            Dark
            Color="primary" OnClick="()=>AddMapping()">
                添加
            </MButton>
        </div>

        @foreach (var item in typeMap)
        {
            <MChip Class="ma-2"
            Color="green"
            Outlined
            Close
            OnCloseClick="()=> DeleteTypeMap(item)">
                @item.Key<p>&gt;&gt;&gt;</p>@item.Value
            </MChip>
        }
    </MCardText>
</MCard>

<MCard Class="mt-2">
    <MToolbar Color="blue">
        <MToolbarTitle>生成模型</MToolbarTitle>
        <MToolbarItems Class="ml-5">
            <MButton Color="success" Class="ml-5" Onclick="CreateClass">生成类</MButton>
            <MButton Color="success" Class="ml-5" OnClick="WriteFile" Loading="WriteFileState"
            Disabled="WriteFileState">

                <LoaderContent>
                    <span>成功</span>
                </LoaderContent>
                <ChildContent>
                    写入到路径
                </ChildContent>
            </MButton>
            <MButton Color="success" Class="ml-5" OnClick="ClearPaths">清除常用路径</MButton>
        </MToolbarItems>
    </MToolbar>
    <MContainer Fluid>
        <MCard>
            <div class="d-flex ml-5 mr-5">
                <MTextField @bind-Value="@nameSpeace"
                Hint="命名空间"
                Label="输入命名空间">
                </MTextField>
                <MTextField @bind-Value="@filePath" Readonly="true"
                Hint="文件输出路径"
                Label="选择路径">
                </MTextField>
                <MButton class="mx-2"
                Fab
                Small
                Dark
                Color="primary" OnClick="()=>OpenFile()">
                    <MIcon>
                        mdi-folder
                    </MIcon>
                </MButton>
                <MButton class="mx-2"
                Dark
                Color="primary" OnClick="()=>AddFilePath()">
                    添加到常用路径
                </MButton>
            </div>
        </MCard>
        <MCard>
            <MRadioGroup @bind-Value="selectedFilePath"
            Column>
                @foreach (var item in filePaths)
                {
                    <MRadio Label="@item.Key"
                    Value="@item">
                    </MRadio>
                }
            </MRadioGroup>
        </MCard>
        <MCard>
            <MTextField @bind-Value="@className"
            Hint="类名"
            Label="输入类名">
            </MTextField>
        </MCard>
        <MCard>
            <MTextarea Clearable
            ClearIcon="mdi-close-circle"
            Label="复制表格内容到此"
            @bind-Value="docText">
            </MTextarea>
        </MCard>
        <MDivider></MDivider>
        <MMonacoEditor Height="@("100%")" InitOptions="InitEditor" @ref="_editor"></MMonacoEditor>
    </MContainer>
</MCard>
@code {
    private AlertTypes AlertType = AlertTypes.Error;
    private bool _alert = false;
    private string errMsg = string.Empty;
    private string docText = string.Empty;
    private List<StringNumber> _amenities = new();
    public List<StringNumber> amenities
    {
        get => _amenities; set
        {
            if (value != _amenities)
            {
                OnTitleColSelectedChangedAfter(value);
                _amenities = value;
            }
        }
    }

    private static readonly List<string> TitleCols = new List<string>()
    {
        "代码","名称","类型","是否必填","备注","占位1","占位2","占位3","占位4","占位5"
    };
    private string _projectType = string.Empty;
    private string projectType
    {
        get => _projectType;
        set
        {
            if (value != _projectType)
            {
                _projectType = value;
                OnSelectedProjectTypeChanged(value);
            }
        }
    }

    private string docFile = string.Empty;
    private List<string> docTitles = new List<string>();

    private List<string> codeTypes = new List<string>();
    private string codeType = string.Empty;
    private string nameSpeace = string.Empty;
    private string filePath = string.Empty;
    private KeyValuePair<string,string> selectedFilePath = new();
    private Dictionary<string,string> filePaths = new();

    [Inject]
    public ISettingService settingService { get; set; }
    [Inject]
    public IServiceProvider serviceProvider { get; set; }
    [Inject]
    public IExInterfaceCodeService ExInterfaceCodeService { get; set; }

    private Dictionary<string, string> typeMap;

    private string codeString = string.Empty;
    private string className = string.Empty;

    private MMonacoEditor _editor;

    private bool WriteFileState = false;

    protected override void OnInitialized()
    {
        base.OnInitialized();
        ExInterfaceSetting exInterfaceSetting = settingService.GetInterfaceSetting();
        typeMap = exInterfaceSetting.typeMap;
        docTitles = exInterfaceSetting.docTitles;
        projectType = exInterfaceSetting.projectType;
        filePaths = exInterfaceSetting.filePaths;
    }

    private async Task<object> InitEditor()
    {
        object options = new
        {
            value = "",
            lineNumbers = "on",
            roundedSelection = false,
            scrollBeyondLastLine = false,
            readOnly = false,
            theme = "vs-dark",
        };
        return options;
    }

    private void OnTitleColSelectedChangedAfter(List<StringNumber> amen)
    {
        //添加
        if (amen.Count > _amenities.Count)
        {
            amen.Where(w => !_amenities.Contains(w))?.ToList()?.ForEach(e =>
            {
                docTitles.Add(TitleCols[e.AsT1]);
            });
        }
        //删除
        if (amen.Count < _amenities.Count)
        {
            _amenities.Where(w => !amen.Contains(w))?.ToList()?.ForEach(e =>
            {
                docTitles.Remove(TitleCols[e.AsT1]);
            });
        }
    }

    private void DeleteDocTitle(string item){
        docTitles.Remove(item);
    }

    private void OnSelectedProjectTypeChanged(string value)
    {
        if (value == "Java")
        {
            codeTypes = DocClassType.JavaTypeList;
        }

        if (value == "CSharp")
        {
            codeTypes = DocClassType.CSharpTypeList;
        }
    }

    private void AddMapping()
    {
        if (string.IsNullOrWhiteSpace(docFile))
        {
            AlertType = AlertTypes.Error;
            errMsg = "文档字段不能为空";
            _alert = true;
            return;
        }
        if (string.IsNullOrWhiteSpace(codeType))
        {
            AlertType = AlertTypes.Error;
            errMsg = "对应字段不能为空";
            _alert = true;
            return;
        }
        if (typeMap.TryGetValue(docFile, out string value))
        {
            AlertType = AlertTypes.Error;
            errMsg = "该字段已对应类型";
            _alert = true;
            return;
        }
        typeMap.Add(docFile, codeType);
    }

    private void SaveSettings()
    {
        ExInterfaceSetting exInterfaceSetting = new()
            {
                docTitles = docTitles,
                projectType = projectType,
                typeMap = typeMap,
                filePaths=filePaths,
            };
        settingService.SaveInterfaceSetting(exInterfaceSetting);
        {
            AlertType = AlertTypes.Info;
            errMsg = "保存成功";
            _alert = true;
        }
    }

    private void DeleteTypeMap(KeyValuePair<string, string> item)
    {
        typeMap.Remove(item.Key);
    }

    private async void OpenFile()
    {
        try
        {
            var directoryPath = await serviceProvider.GetService<IDirectoryPicker>().PickDirectoryAsync();
            if (!string.IsNullOrEmpty(directoryPath))
            {
                filePath = directoryPath;
                StateHasChanged();
            }
        }
        catch (Exception ex)
        {
        }
    }

    private void AddFilePath()
    {
        if (string.IsNullOrWhiteSpace(nameSpeace)){
            AlertType = AlertTypes.Error;
            errMsg = "命名空间不能为空！";
            _alert = true;
        }
        if (string.IsNullOrWhiteSpace(filePath))
        {
            AlertType = AlertTypes.Error;
            errMsg = "路径不能为空！";
            _alert = true;
        }
        if (filePaths.ContainsKey(nameSpeace)){
            AlertType = AlertTypes.Error;
            errMsg = $"当前命名空间已绑定路径{filePaths[nameSpeace]}";
            _alert = true;
        }
        filePaths.Add(nameSpeace,filePath);
    }

    private void ClearPaths(){
        filePaths.Clear();
        SaveSettings();
    }
    /// <summary>
    /// 生成代码
    /// </summary>
    private async void CreateClass(){
        if (string.IsNullOrWhiteSpace(className)){
            AlertType = AlertTypes.Error;
            errMsg = "类名不能为空！";
            _alert = true;
        }
        if (string.IsNullOrWhiteSpace(selectedFilePath.Key))
        {
            AlertType = AlertTypes.Error;
            errMsg = "命名空间不能为空！";
            _alert = true;
        }
        try
        {
            codeString = ExInterfaceCodeService.CreateCode(className, selectedFilePath.Key, docText, projectType, docTitles, typeMap);
        }
        catch (Exception ex)
        {
            AlertType = AlertTypes.Error;
            errMsg = $"生成代码出错！{ex.Message}";
            _alert = true;
        }
        if(projectType=="Java"){
            await _editor.SetModelLanguageAsync("java");
        }
        if (projectType == "CSharp"){
            await _editor.SetModelLanguageAsync("csharp");
        }
        await _editor.SetValueAsync(codeString);
        StateHasChanged();
    }
    /// <summary>
    /// 写到文件
    /// </summary>
    private async void WriteFile(){
        var fileName = string.Empty;
        if(projectType=="Java"){
            fileName = $"{className}.java";
        }
        if(projectType=="CSharp"){
            fileName = $"{className}.cs";
        }
        var fileFullPath = Path.Combine(selectedFilePath.Value, fileName);
        File.WriteAllText(fileFullPath, codeString, new UTF8Encoding(false));

        WriteFileState = true;
        StateHasChanged();
        await Task.Run(() =>
        {
            Thread.Sleep(3000);
        });
        WriteFileState = false;
        StateHasChanged();
    }
}